package com.jinzhi.common.wxpay.service.impl;


import com.google.gson.Gson;
import com.jinzhi.common.utils.Result;
import com.jinzhi.common.wxpay.service.WxPayCommonService;
import com.jinzhi.common.wxpay.utils.MtWeChatConstant;
import com.jinzhi.jzapi.domain.UserDO;
import com.jinzhi.jzapi.utils.JWTUtil;
import com.jinzhi.jzweb.service.JazCoursesOrderService;
import com.jinzhi.jzweb.service.JazCoursesService;
import com.jinzhi.jzweb.service.JazUserOrderService;
import com.jinzhi.wxpay.config.WxPayConfigZF;
import com.jinzhi.wxpay.entity.OrderInfo;
import com.jinzhi.wxpay.enums.WechatPay2ValidatorForRequest;
import com.jinzhi.wxpay.enums.wxpay.WxApiType;
import com.jinzhi.wxpay.enums.wxpay.WxNotifyType;
import com.jinzhi.wxpay.util.GetOpenIdUtil;
import com.jinzhi.wxpay.util.HttpUtils;
import com.jinzhi.wxpay.vo.R;
import com.wechat.pay.contrib.apache.httpclient.auth.Verifier;
import com.wechat.pay.java.core.Config;
import com.wechat.pay.java.core.RSAAutoCertificateConfig;
import com.wechat.pay.java.service.refund.RefundService;
import com.wechat.pay.java.service.refund.model.AmountReq;
import com.wechat.pay.java.service.refund.model.CreateRequest;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.util.EntityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.locks.ReentrantLock;


//当前接口的实现类
@Slf4j
@Service
public class WxPayCommonServiceImpl implements WxPayCommonService {
    @Resource
    private WxPayConfigZF wxPayConfigZF;

    @Resource
    private CloseableHttpClient  wxPayClient;


    /**
     * 小程序支付接口
     * @param orderName 订单名称
     * @param openid
     * @param totalFee 金额
     * @param orderNo 订单编号
     *        wxNotifyType   回调地址
     * @return
     * @throws Exception
     */
    @Override
    public Map<String, Object> jsapiNativePay(String orderName,String appid, String openid, BigDecimal totalFee, String orderNo,String wxNotifyType) throws Exception {

        System.out.println("++++++++++++++++++++++++++++++++++++++++参数1orderName："+orderName);
        System.out.println("++++++++++++++++++++++++++++++++++++++++参数appid："+appid);
        System.out.println("++++++++++++++++++++++++++++++++++++++++参数openid："+openid);
        System.out.println("++++++++++++++++++++++++++++++++++++++++参数totalFee："+totalFee);
        System.out.println("++++++++++++++++++++++++++++++++++++++++参数orderNo："+orderNo);
        System.out.println("++++++++++++++++++++++++++++++++++++++++参数wxNotifyType："+wxNotifyType);


        //微信登录授权获取openid
//        String openid = GetOpenIdUtil.decodeUserInfo(wxPayConfig.getAppid(), code, wxPayConfig.getApiV3Key());
        //调用统一下单api
        log.info("调用统一下单API");
        //调用统一下单API
        HttpPost httpPost = new HttpPost(wxPayConfigZF.getDomain().concat(WxApiType.JSAPI_PAY.getType()));
        // 请求body参数
        Gson gson = new Gson();
        Map paramsMap = new HashMap();
        log.info("appid========>"+ appid);
        paramsMap.put("appid", appid);
        paramsMap.put("mchid", wxPayConfigZF.getMchId());
        paramsMap.put("description", orderName);
        paramsMap.put("out_trade_no", orderNo);//为自动生成
//        paramsMap.put("notify_url", wxPayConfigZF.getNotifyDomain().concat(WxNotifyType.NATIVE_NOTIFY.getType()));//支付通知接口（支付成功后自动调用这个接口）
//        paramsMap.put("notify_url", "http://jzwypay.w1.luyouxia.net"+ wxNotifyType);//支付通知接口（支付成功后自动调用这个接口）
        paramsMap.put("notify_url", wxPayConfigZF.getNotifyDomain()+ wxNotifyType);//支付通知接口（支付成功后自动调用这个接口）


        Map amountMap = new HashMap();
        Map payerMap = new HashMap();
        BigDecimal d = new BigDecimal(100);//微信支付算的是分，因此这里需要乘以100
        int fee =  d.multiply(totalFee).intValue();//去除多余的0
        amountMap.put("total", fee);//总金额
        amountMap.put("currency", "CNY");//货币类型
        payerMap.put("openid",openid);
        paramsMap.put("amount", amountMap);
        paramsMap.put("payer", payerMap);
        //将参数转为json字符串
        String jsonParams = gson.toJson(paramsMap);
        log.info("请求参数 ===> {}" + jsonParams);

        //将请求参数封装进Entity对象中
        StringEntity entity = new StringEntity(jsonParams,"utf-8");
        entity.setContentType("application/json");
        httpPost.setEntity(entity);
        httpPost.setHeader("Accept", "application/json");
        log.info("将请求参数封装进Entity对象中===>"+httpPost);
        //完成签名并执行请求
        CloseableHttpResponse response = wxPayClient.execute(httpPost);
        log.info("获取用户私钥成功=======》"+response);
        //对请求结果的处理
        try {
            System.out.println("================失败==============="+response);
            String bodyAsString = EntityUtils.toString(response.getEntity()); //响应体
            log.info("响应体======》"+response.getEntity());
            int statusCode = response.getStatusLine().getStatusCode(); //响应状态码
            log.info("响应状态码："+statusCode);
            if (statusCode == 200) { //处理成功
                log.info("成功, 返回结果 = " + bodyAsString);
            } else if (statusCode == 204) { //处理成功，无返回Body
                log.info("成功");
            } else {
                log.info("小程序 下单失败，响应码 " + statusCode+ ",返回结果 = " + bodyAsString);
                throw new IOException("request failed");
            }
            //响应结果
            HashMap<String,String> resultMap = gson.fromJson(bodyAsString, HashMap.class);
            log.info("响应结果=====>"+resultMap);

            //返回所需的参数
            Map<String, Object> map = new HashMap<>();
            map.put("total_fee", fee);
            //返回小程序调起微信支付所需要的参数
            //小程序id
            map.put("appid", appid);
            //时间戳
            SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");//得到一个时间戳
            String  newDate = sdf.format(new Date());
            map.put("timeStamp", newDate);
            //随机字符串
            Random random = new Random();//得到一个随机数字符串
            String nonceStr = "";
            for (int i = 0; i < 3; i++){
                nonceStr += random.nextInt(10);//十位数字的随机字符串
            }
            map.put("nonceStr",nonceStr);
            //订单详情扩展字符串
            map.put("package","prepay_id="+resultMap.get("prepay_id"));
            //签名方式
            map.put("signType","RSA");
            //签名(需要算法计算)
            String paySign = GetOpenIdUtil.getSign(appid,Long.parseLong(newDate),nonceStr,"prepay_id="+resultMap.get("prepay_id"));
            map.put("paySign",paySign);
            return map;
        } finally {
            response.close();
        }
    }

    /**
     * 小程序退款接口
     * @param transactionId 微信订单编号
     * @param outRefundNo 退款单号
     * @param totalAmount 退款金额
     * @param refundAmount 退款金额
     * @return Map<String, Object> 包含退款结果信息的Map
     *
     *          * 注意:
     *          * 1.以上参数都需要按照实际情况填写,大部分参数都是付款成功之后的回调数据
     *          * 2.以上退款是必要参数,如果想要填写其他参数参考文档:https://pay.weixin.qq.com/docs/merchant/apis/jsapi-payment/create.html
     *          * 3.SDK的微信支付的退款代码参考:https://github.com/wechatpay-apiv3/wechatpay-java/blob/main/service/src/main/java/com/wechat/pay/java/service/refund/RefundService.java
     *
     */
    public Result<?> jsapiRefund(String transactionId, String outRefundNo, BigDecimal totalAmount, BigDecimal refundAmount) {
        // 使用自动更新平台证书的RSA配置
        // 一个商户号只能初始化一个配置，否则会因为重复的下载任务报错
        Config config = new RSAAutoCertificateConfig.Builder()
                .merchantId(MtWeChatConstant.MERCHANT_ID)
                .privateKeyFromPath(MtWeChatConstant.MERCHANT_PRIVATE_KEY_PATH)
                .merchantSerialNumber(MtWeChatConstant.MERCHANT_SERIAL_NUMBER)
                .apiV3Key(MtWeChatConstant.API_V3_KEY)
                .build();
        //构造申请退款对象
        RefundService service = new RefundService.Builder().config(config).build();
        //请求参数
        CreateRequest request = new CreateRequest();
        //设置退款金额 根据自己的实际业务自行填写
        Long totalFee = totalAmount.multiply(new BigDecimal(100)).longValue();//去除多余的0; // 退款金额，单位为分
        Long fee = refundAmount.multiply(new BigDecimal(100)).longValue();//去除多余的0; // 退款金额，单位为分
        AmountReq amountReq = new AmountReq();
        amountReq.setRefund(fee);
        amountReq.setTotal(totalFee);
        amountReq.setCurrency("CNY");
        request.setAmount(amountReq);
        //支付成功后回调回来的transactionId 按照实际情况填写
        request.setTransactionId(transactionId);
        //支付成功后回调回来的transactionId 按照实际情况填写
        request.setOutRefundNo(outRefundNo);
        //退款成功的回调地址
        request.setNotifyUrl(MtWeChatConstant.REFUND_NOTIFY_URL);
        //发起请求,申请退款
        com.wechat.pay.java.service.refund.model.Refund refund = service.create(request);
        //调用成功的响应数据
        System.out.println(refund);

        return Result.ok(refund.getStatus());
    }






}
